package com.example.demo.methodIntrospector;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Map;

/* ━━━━━━佛祖保佑━━━━━━
 *                  ,;,,;
 *                ,;;'(    社
 *      __      ,;;' ' \   会
 *   /'  '\'~~'~' \ /'\.)  主
 * ,;(      )    /  |.     义
 *,;' \    /-.,,(   ) \    码
 *     ) /       ) / )|    农
 *     ||        ||  \)
 *     (_\       (_\
 * ━━━━━━永无BUG━━━━━━
 * @author ：zjq
 * @date ：2021/2/18 2:25
 * @description: TODO                   测试 MethodIntrospector.selectMethods 方法
 * @version: V1.0
 * @slogan: 天下风云出我辈，一入代码岁月催
 */
@Component
@Slf4j
public class MyTestExcutor implements SmartInitializingSingleton, ApplicationContextAware {

    // ---------------------- applicationContext ----------------------
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyTestExcutor.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /***
     *  模拟  MethodIntrospector.selectMethods 方法
     */
    @Override
    public void afterSingletonsInstantiated() {
        String[] beanDefinitionNames = applicationContext.getBeanNamesForType(Object.class, false, true);

        Map<Method, Zjq> annotatedMethods = null;
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = applicationContext.getBean(beanDefinitionName);
            try {
                //TODO  核心方法 拿到 zjq 注解
                annotatedMethods = MethodIntrospector.selectMethods(bean.getClass(),
                        new MethodIntrospector.MetadataLookup<Zjq>() {
                            @Override
                            public Zjq inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, Zjq.class);
                            }
                        });
            } catch (Throwable ex) {
                log.error("zjq  method-jobhandler resolve error for bean[" + beanDefinitionName + "].", ex);
            }

            if (annotatedMethods == null || annotatedMethods.isEmpty()) {
                continue;
            }
            // 遍历  annotatedMethods
            for(Map.Entry<Method,Zjq> e:annotatedMethods.entrySet()){
                // 拿到 方法
                Method method = e.getKey();
                // 拿到 balue
                Zjq zjq = e.getValue();
                if (zjq == null) {
                    continue;
                }
                // 拿到自定义注解的值
                String name=zjq.value();System.out.println(name);
                // 拿到方法的参数
                Parameter[] parameters = method.getParameters();
                try {
                    // 调用方法
                    method.invoke(bean,"qiuqiu",1);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

            }

        }
    }

}
